package com.itlong.cloud.utils.network.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.property.PropertyUserLoginDTO;
import com.itlong.cloud.POJO.VO.IpGetAddressFromTaobaoVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;



/**
 * <desc>
 * HTTP协议网络处理帮助类。
 * </desc>
 *
 * @createDate 2017/9/21
 */
public class HttpProtocolUtil {

    protected static final Logger LOG = LoggerFactory.getLogger(HttpProtocolUtil.class);



    //static {
        //System.setProperty("https.protocols", "TLSv1");
        //System.setProperty("https.protocols", "TLSv1.2");
    //}

    private HttpProtocolUtil() {
        super();
    }

    /**
     * <desc>
     * 执行HTTP POST请求.
     * <desc/>
     *
     * @param remoteUrl 请求地址
     * @param content   参数
     * @return xx
     * @author Wenchao.L
     * @createDate 2017/9/21
     */
    public static String httpPost(
            String remoteUrl,
            String content) {

        if (StringUtils.isBlank(remoteUrl)) {
            return PlatformConstants.ERRINFO_REMOTEURL;
        }

        if (StringUtils.isBlank(content)) {
            return PlatformConstants.ERRINFO_CONTENTISNULL;
        }

        URL url = null;
        HttpURLConnection hconn = null;
        BufferedWriter writer = null;

        try {
            url = new URL(remoteUrl);
            hconn = (HttpURLConnection) url.openConnection();
            hconn.setConnectTimeout(5000 * 10);    //打开连接时间等待超时5秒
            hconn.setReadTimeout(10000 * 10);    //等待读取返回数据超时10秒 JDK 1.4 没有这个方法
            System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
            System.setProperty("sun.net.client.defaultReadTimeout", "10000");
            hconn.setDoOutput(true);
            hconn.setRequestMethod(PlatformConstants.METHOD_POST);
            hconn.setRequestProperty("Accept", "application/json;");
            hconn.setRequestProperty("Content-Type", "application/json;charset=utf-8");

            writer = new BufferedWriter(new OutputStreamWriter(hconn.getOutputStream(),
                    PlatformConstants.DEFAULT_CHARSET));

            writer.write(content.toString());
            writer.flush();
            writer.close();

            InputStream in = hconn.getInputStream();
            StringBuffer strbuf = new StringBuffer();
            InputStreamReader isr = null;
            isr = new InputStreamReader(in, PlatformConstants.DEFAULT_CHARSET);
            BufferedReader br = new BufferedReader(isr);
            String temp = "";
            for (int i = 0; i < 500; i++) {
                while ((temp = br.readLine()) != null)
                    strbuf.append(temp + "\r\n");
            }
            in.close();
            String result = strbuf.toString();
            return result;

        } catch (FileNotFoundException e1) {
            LOG.error(PlatformConstants.ERRINFO_FILENOTFOUNDEXCEPTION + remoteUrl, e1);
            return createOutXML(PlatformConstants.ERRINFO_FILENOTFOUNDEXCEPTION);
        } catch (java.net.SocketTimeoutException e2) {
            LOG.error(PlatformConstants.ERRINFO_TIMEOUTEXCEPTION, e2);
            return createOutXML(PlatformConstants.ERRINFO_TIMEOUTEXCEPTION);
        } catch (java.net.SocketException e3) {
            LOG.error(PlatformConstants.ERRINFO_SOCKETEXCEPTION, e3);
            return createOutXML(PlatformConstants.ERRINFO_SOCKETEXCEPTION);
        } catch (Exception e) {
            LOG.error(PlatformConstants.ERRINFO_OTHEREXCEPTION, e);
            return createOutXML(PlatformConstants.ERRINFO_OTHEREXCEPTION);

        } finally {
            if (hconn != null)
                hconn.disconnect();
            if (writer != null)
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    /**
     * <desc>
     * 错误码转化信息.
     * <desc/>
     *
     * @param callResult 错误码
     * @return 错误提示
     * @author Wenchao.L
     * @createDate 2017/9/21
     */
    public static String createOutXML(String callResult) {
        StringBuffer reVol = new StringBuffer();
        reVol.append("<?xml version=\"1.0\" encoding=\"GBK\"?><PACKET type=\"RESPONSE\" version=\"1.0\" >");
        reVol.append("<HEAD><REQUEST_TYPE>99</REQUEST_TYPE><RESPONSE_CODE>0</RESPONSE_CODE>");
        reVol.append("<ERROR_CODE>");
        reVol.append(callResult);
        reVol.append("</ERROR_CODE><ERROR_MESSAGE>");

        if (PlatformConstants.ERRINFO_FILENOTFOUNDEXCEPTION.equals(callResult)) {
            reVol.append("不能访问服务器");
        }
        if (PlatformConstants.ERRINFO_TIMEOUTEXCEPTION.equals(callResult)) {
            reVol.append("连接服务器超时");
        }
        if (PlatformConstants.ERRINFO_SOCKETEXCEPTION.equals(callResult)) {
            reVol.append("无法连接服务器");
        }
        if (PlatformConstants.ERRINFO_OTHEREXCEPTION.equals(callResult)) {
            reVol.append("连接服务器时发生异常");
        }
        reVol.append("</ERROR_MESSAGE></HEAD></PACKET>");
        return reVol.toString();
    }


    /**
     * <desc>
     * 执行HTTP GET请求.
     * <desc/>
     *
     * @param remoteUrl 请求地址
     * @param params    请求参数
     * @return 响应字符串
     * @author Wenchao.L
     * @createDate 2017/9/21
     */
    public static String doGet(String remoteUrl, Map<String, String> params) throws IOException, Exception {
        return doGet(remoteUrl, params, PlatformConstants.DEFAULT_CHARSET, null);
    }


    /**
     * <desc>
     * 执行HTTP GET请求.
     * <desc/>
     *
     * @param remoteUrl 请求地址
     * @param params    请求参数
     * @param akey      短信需要的key
     * @return 响应字符串
     * @author Wenchao.L
     * @createDate 2017/9/21
     */
    public static String doGet(String remoteUrl, Map<String, String> params, String akey) throws IOException, Exception {
        return doGet(remoteUrl, params, PlatformConstants.DEFAULT_CHARSET, akey);
    }


    /**
     * <desc>
     * 执行HTTP GET请求.
     * <desc/>
     *
     * @param url     请求地址
     * @param params  请求参数
     * @param charset 字符集，如UTF-8, GBK, GB2312
     * @return xx
     * @author Wenchao.L
     * @createDate 2017/9/21
     */
    public static String doGet(String url, Map<String, String> params, String charset, String akey)
            throws Exception {
        HttpURLConnection conn = null;
        String rsp = null;

        try {
            String ctype = "application/x-www-form-urlencoded;charset=" + charset;
            String query = buildQuery(params, charset);
            try {
                conn = getConnection(buildGetUrl(url, query), PlatformConstants.METHOD_GET, ctype, akey);
            } catch (IOException e) {
                Map<String, String> map = getParamsFromUrl(url);
                throw e;
            }

            try {
                rsp = getResponseAsString(conn);
            } catch (IOException e) {
                Map<String, String> map = getParamsFromUrl(url);
                throw e;
            }

        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }

        return rsp;
    }

    /**
     * <desc>
     * 辅助方法：构建HttpURLConnection请求连接。.
     * <desc/>
     *
     * @param url    URL。
     * @param method GET/POST/PUT/DELETE等。
     * @param ctype  Content-Type。
     * @return HttpURLConnection
     * @author Wenchao.L
     * @createDate 2017/9/21
     */
    private static HttpURLConnection getConnection(URL url, String method, String ctype, String akey) throws Exception {

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod(method);
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setRequestProperty("Accept", "text/xml,text/javascript,text/html,application/json");
        conn.setRequestProperty("User-Agent", "top-sdk-java");
        conn.setRequestProperty("Content-Type", ctype);
        if (StringUtils.isNotBlank(akey)) {
            conn.setRequestProperty("apikey", akey);
        }
        return conn;
    }




    public static String buildQuery(Map<String, String> params, String charset) throws IOException {
        if (params == null || params.isEmpty()) {
            return null;
        }

        StringBuilder query = new StringBuilder();
        Set<Map.Entry<String, String>> entries = params.entrySet();
        boolean hasParam = false;

        for (Map.Entry<String, String> entry : entries) {
            String name = entry.getKey();
            String value = entry.getValue();
            // 忽略参数名或参数值为空的参数
            if (StringUtils.isNotBlank(name) && StringUtils.isNotBlank(value)) {
                if (hasParam) {
                    query.append("&");
                } else {
                    hasParam = true;
                }

                query.append(name).append("=").append(URLEncoder.encode(value, charset));
            }
        }

        return query.toString();
    }

    protected static String getResponseAsString(HttpURLConnection conn) throws IOException {
        String charset = getResponseCharset(conn.getContentType());
        InputStream es = conn.getErrorStream();
        if (es == null) {
            return getStreamAsString(conn.getInputStream(), charset);
        } else {
            String msg = getStreamAsString(es, charset);
            if (StringUtils.isEmpty(msg)) {
                throw new IOException(conn.getResponseCode() + ":" + conn.getResponseMessage());
            } else {
                throw new IOException(msg);
            }
        }
    }

    private static String getStreamAsString(InputStream stream, String charset) throws IOException {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream, charset));
            StringWriter writer = new StringWriter();

            char[] chars = new char[256];
            int count = 0;
            while ((count = reader.read(chars)) > 0) {
                writer.write(chars, 0, count);
            }

            return writer.toString();
        } finally {
            if (stream != null) {
                stream.close();
            }
        }
    }

    private static String getResponseCharset(String ctype) {
        String charset = PlatformConstants.DEFAULT_CHARSET;

        if (!StringUtils.isEmpty(ctype)) {
            String[] params = ctype.split(";");
            for (String param : params) {
                param = param.trim();
                if (param.startsWith("charset")) {
                    String[] pair = param.split("=", 2);
                    if (pair.length == 2) {
                        if (!StringUtils.isEmpty(pair[1])) {
                            charset = pair[1].trim();
                        }
                    }
                    break;
                }
            }
        }

        return charset;
    }


    private static Map<String, String> getParamsFromUrl(String url) {
        Map<String, String> map = null;
        if (url != null && url.indexOf('?') != -1) {
            map = splitUrlQuery(url.substring(url.indexOf('?') + 1));
        }
        if (map == null) {
            map = new HashMap<String, String>();
        }
        return map;
    }

    /**
     * 从URL中提取所有的参数。
     *
     * @param query URL地址
     * @return 参数映射
     */
    public static Map<String, String> splitUrlQuery(String query) {
        Map<String, String> result = new HashMap<String, String>();

        String[] pairs = query.split("&");
        if (pairs != null && pairs.length > 0) {
            for (String pair : pairs) {
                String[] param = pair.split("=", 2);
                if (param != null && param.length == 2) {
                    result.put(param[0], param[1]);
                }
            }
        }

        return result;
    }

    /**
     * 为内容中没有包含a标签的url增加a标签。
     *
     * @param content 内容
     * @return 拼接后的内容
     */
    public static String convertContent(String content) {
        if (content.indexOf("<a href") == -1) {
            if (content.indexOf("http://") != -1) {
                content = content.replaceAll("(?is)(?<!')(http://[/\\.\\w]+)", "<a href='$1' target='blank_'>$1</a>");
            }
        }
        return content;
    }


    /**
     * <p/>
     * 获取请求ip地址
     * <p/>
     *
     * @param request
     * @return
     * @aurhor Jiaqi.X
     * @createDate 2017/10/13
     */
    public static String getIpAddr(HttpServletRequest request) {
        if (null == request) {
            return null;
        }
        String proxs[] = {"X-Forwarded-For", "Proxy-Client-IP",
                "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR", "x-real-ip"};
        String ip = null;
        ip:
        for (String prox : proxs) {
            ip = request.getHeader(prox);
            if ("X-Forwarded-For".equals(prox)) {
                //如果是多级反向代理，取第一个ip为真实ip
                String[] ips = StringHandlerUtil.splitString(ip);
                if (ips.length > 0) {
                    ip = ips[0];
                    break ip;
                }
            }
            if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
                continue;
            } else {
                break;
            }
        }
        if (StringUtils.isBlank(ip)) {
            return request.getRemoteAddr();
        }
        return ip;
    }


    /**
     * <desc>
     * 将map填充至request attribute
     * </desc>
     *
     * @param params
     * @param request
     * @author Jiaqi.X
     * @createDate 2018/05/17
     */
    public static void setRequestAttributes(Map<String, Object> params, HttpServletRequest request) {
        params.keySet().forEach(key -> {
            request.setAttribute(key, params.get(key));
        });
    }

    /**
     * <desc>
     * 将请求所带的参数填充到DTO中去，主要用于云对讲SDK
     * </desc>
     *
     * @param clazz   目标DTO的Class实例
     * @param request HttpServletRequest请求域对象
     * @param <T>     目标DTO泛型
     * @return 填充数据后的DTO实例
     * @author wangzhi
     * @createDate 2018/05/16
     */
    public static <T> T parseRequestParamToDTO(Class<T> clazz, HttpServletRequest request) {
        T t = null;
        try {
            t = clazz.newInstance();
            // 获取DTO中已声明的属性集合
            Field[] fields = clazz.getDeclaredFields();
            List<Field> fieldList = new ArrayList<>(Arrays.asList(fields));
            // 将父类属性也全部拿到
            Class sClazz = clazz;
            while (true) {
                sClazz = sClazz.getSuperclass();
                if (sClazz == null) {
                    break;
                }
                Field[] superFields = sClazz.getDeclaredFields();
                if (superFields != null) {
                    fieldList.addAll(Arrays.asList(superFields));
                }
            }
            for (Field field : fieldList) {
                // 过滤被final、static修饰的成员变量
                if ((field.getModifiers() & Modifier.FINAL) > 0 || (field.getModifiers() & Modifier.STATIC) > 0) {
                    continue;
                }
                // 取消private的限制
                field.setAccessible(true);
                // 获取属性的数据类型
                Class<?> fieldType = field.getType();
                // 获取属性名
                String fieldName = field.getName();
                // 从request中获取请求参数
                Object fieldValue = request.getAttribute(fieldName);
                if (fieldValue == null) {
                    fieldValue = request.getParameter(fieldName);
                }
                if (fieldValue == null) {
                    continue;
                }
                // 填充数据
                if (fieldType == String.class) {
                    field.set(t, fieldValue.toString());
                } else if (fieldType == long.class || fieldType == Long.class) {
                    field.set(t, "".equals(fieldValue.toString()) ? null : NumberUtils.toLong(fieldValue.toString()));
                } else if (fieldType == int.class || fieldType == Integer.class) {
                    field.set(t, "".equals(fieldValue.toString()) ? null : NumberUtils.toInt(fieldValue.toString()));
                } else if (fieldType == Date.class) {
                    field.set(t, "".equals(fieldValue.toString()) ? null : DateUtil.parseString("yyyy-MM-dd HH:mm:ss", fieldValue.toString()));
                } else if (fieldType == boolean.class || fieldType == Boolean.class) {
                    field.set(t, "".equals(fieldValue.toString()) ? null : Boolean.valueOf(fieldValue.toString()));
                } else if (fieldType == BigInteger.class) {
                    field.set(t, "".equals(fieldValue.toString()) ? null : new BigInteger(fieldValue.toString()));
                } else if (fieldType == BigDecimal.class) {
                    field.set(t, "".equals(fieldValue.toString()) ? null : new BigDecimal(fieldValue.toString()));
                } else if (fieldType == List.class) {
                    field.set(t, "".equals(fieldValue.toString()) ? null : JSON.parseObject(fieldValue.toString(), List.class));
                }
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * <desc>
     * 处理get请求
     * </desc>
     *
     * @param host    请求服务主机路由
     * @param path    请求服务相对路径
     * @param method  请求方法
     * @param headers 请求头map
     * @param querys  请求参数map，key为mobile，value为手机号
     * @return
     * @throws Exception
     * @author wangzhi
     * @createDate 2018/05/07
     */
    public static HttpResponse doGet(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys) {
        HttpGet request = null;
        try {
            HttpClient httpClient = wrapClient();

            request = new HttpGet(buildUrl(host, path, querys));
            for (Map.Entry<String, String> e : headers.entrySet()) {
                request.addHeader(e.getKey(), e.getValue());
            }

            HttpResponse response = httpClient.execute(request);
            if (response == null || response.getStatusLine().getStatusCode() != 200) {
                request.abort();
                return null;
            }
            return response;
        } catch (Exception e) {
            if (request != null) {
                request.abort();
            }
            return null;
        }
    }

    /**
     * 执行HTTP GET请求。
     *
     * @param url 请求地址
     * @param params 请求参数
     * @return 响应字符串
     * @throws IOException
     */
    public static String httpGet(String url, Map<String, String> params) throws IOException,Exception {
        return httpGet(url, params,"UTF-8");
    }

    /**
     * 执行HTTP GET请求。
     *
     * @param url 请求地址
     * @param params 请求参数
     * @return 响应字符串
     * @throws IOException
     */
    public static String httpGet(String url, Map<String, String> params,String charset)
            throws Exception {
        HttpURLConnection conn = null;
        String rsp = null;

        try {
            String ctype = "application/x-www-form-urlencoded;charset=" + charset;
            String query = buildQuery(params, charset);
            try{
                conn = getConnection(buildGetUrl(url, query), "GET", ctype);
            }catch(IOException e){
                Map<String, String> map=getParamsFromUrl(url);
                throw e;
            }

            try{
                rsp = getResponseAsString(conn);
            }catch(IOException e){
                Map<String, String> map=getParamsFromUrl(url);
                throw e;
            }

        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }

        return rsp;
    }

    /**
     * 辅助方法：构建HttpURLConnection请求连接。
     *
     * @param url URL。
     * @param method GET/POST/PUT/DELETE等。
     * @param ctype Content-Type。
     * @return {@link java.net.HttpURLConnection}。
     * @throws java.io.IOException
     */
    private static HttpsURLConnection getConnection(URL url, String method, String ctype) throws Exception {
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

        TrustManager[] tm = {new TrustAnyTrustManager()};
        SSLContext sc = SSLContext.getInstance("SSL", "SunJSSE");
        sc.init(null, tm, new java.security.SecureRandom());

        conn.setSSLSocketFactory(sc.getSocketFactory());
        conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
        conn.setInstanceFollowRedirects(true);
        conn.setRequestMethod(method);
        conn.setUseCaches(false);
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setRequestProperty("Accept", "text/xml,text/javascript,text/html,application/json");
        conn.setRequestProperty("User-Agent", "hongling-api-interface");
        conn.setRequestProperty("Content-Type", ctype);

        return conn;
    }

    /**
     * Https必要实现类
     */
    private static class TrustAnyTrustManager implements X509TrustManager {
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[] {};
        }
    }

    /**
     * Https必要实现类
     */
    private static class TrustAnyHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    private static URL buildGetUrl(String strUrl,String query) throws IOException {
        URL url = new URL(strUrl);
        if (StringUtils.isEmpty(query)) {
            return url;
        }

        if (StringUtils.isEmpty(url.getQuery())) {
            if (strUrl.endsWith("?")) {
                strUrl = strUrl + query;
            } else {
                strUrl = strUrl + "?" + query;
            }
        } else {
            if (strUrl.endsWith("&")) {
                strUrl = strUrl + query;
            } else {
                strUrl = strUrl + "&" + query;
            }
        }

        return new URL(strUrl);
    }

    /**
     * <desc>
     * 构造url
     * </desc>
     *
     * @param host
     * @param path
     * @param querys
     * @return
     * @throws UnsupportedEncodingException
     * @author wangzhi
     * @createDate 2018/05/07
     */
    private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
        StringBuilder sbUrl = new StringBuilder();
        sbUrl.append(host);
        if (!StringUtils.isBlank(path)) {
            sbUrl.append(path);
        }
        if (null != querys) {
            StringBuilder sbQuery = new StringBuilder();
            for (Map.Entry<String, String> query : querys.entrySet()) {
                if (0 < sbQuery.length()) {
                    sbQuery.append("&");
                }
                if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
                    sbQuery.append(query.getValue());
                }
                if (!StringUtils.isBlank(query.getKey())) {
                    sbQuery.append(query.getKey());
                    if (!StringUtils.isBlank(query.getValue())) {
                        sbQuery.append("=");
                        sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
                    }
                }
            }
            if (0 < sbQuery.length()) {
                sbUrl.append("?").append(sbQuery);
            }
        }

        return sbUrl.toString();
    }

    /**
     * <desc>
     * 包装https协议；Httpclient 实现https请求，绕过SSL加密
     * </desc>
     *
     * @return
     * @author wangzhi
     * @createDate 2018/05/07
     */
    private static HttpClient wrapClient() {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                //信任所有
                public boolean isTrusted(X509Certificate[] chain,
                                         String authType) {
                    return true;
                }
            }).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }

    /**
     * <desc>
     *      使用百度免费接口获取ip地址归属地
     * </desc>
     *
     * @param ip ip地址
     * @return 归属地
     * @author wangzhi
     * @createDate 2018/12/28
     */
    public static String getIpAddressFromBaidu(String ip){
        try {
            String url = "https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query=" + ip + "&resource_id=6006&format=json";
            String jsonStr = HttpProtocolUtil.doGet(url, null);
            Map<String, Object> map = JsonUtil.JsonToMap(jsonStr);
            // 拿到返回数据data
            Object data = map.get("data");
            String dataStr = data.toString();
            // 返回数据去掉首尾 []
            String dataJson = dataStr.substring(1, dataStr.length() - 1);
            Map<String, Object> dataMap = JsonUtil.JsonToMap(dataJson);
            // 拿到归属地
            String[] addressArr = dataMap.get("location").toString().split(" ");
            return addressArr[0];
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * <desc>
     *      执行HTTP POST请求只针对灵云快智.
     * <desc/>
     *
     * @param remoteUrl 请求地址
     * @param content   参数
     * @return xx
     * @author JuGuang.S
     * @createDate 2018/07/12
     */
    public static String httpPostByLykz(
            String remoteUrl,
            String content, String nowTime, String accountSid) {

        if (StringUtils.isBlank(remoteUrl)) {
            return PlatformConstants.ERRINFO_REMOTEURL;
        }

        if (StringUtils.isBlank(content)) {
            return PlatformConstants.ERRINFO_CONTENTISNULL;
        }

        URL url = null;
        HttpURLConnection hconn = null;
        BufferedWriter writer = null;

        try {
            url = new URL(remoteUrl);
            hconn = (HttpURLConnection) url.openConnection();
            hconn.setConnectTimeout(5000 * 10);    //打开连接时间等待超时5秒
            hconn.setReadTimeout(10000 * 10);    //等待读取返回数据超时10秒 JDK 1.4 没有这个方法
            System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
            System.setProperty("sun.net.client.defaultReadTimeout", "10000");
            hconn.setDoOutput(true);
            hconn.setRequestMethod(PlatformConstants.METHOD_POST);
            hconn.setRequestProperty("Accept", "application/json;");
            hconn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
            //Authorization包头验证信息 使用Base64编码（账户Id + 冒号 + 时间戳）


            final Base64.Encoder encoder = Base64.getEncoder();
            //final String context = String.format("%s%s%s",LYKZ_ACCOUNT_SID,":",nowTime);
            final String context = String.format("%s%s%s", accountSid, ":", nowTime);
            final byte[] textByte = context.getBytes("UTF-8");
            //编码
            final String authorization = encoder.encodeToString(textByte);
            hconn.setRequestProperty("Authorization", authorization);


            writer = new BufferedWriter(new OutputStreamWriter(hconn.getOutputStream(),
                    PlatformConstants.DEFAULT_CHARSET));

            writer.write(content.toString());
            writer.flush();
            writer.close();

            InputStream in = hconn.getInputStream();
            StringBuffer strbuf = new StringBuffer();
            InputStreamReader isr = null;
            isr = new InputStreamReader(in, PlatformConstants.DEFAULT_CHARSET);
            BufferedReader br = new BufferedReader(isr);
            String temp = "";
            for (int i = 0; i < 500; i++) {
                while ((temp = br.readLine()) != null)
                    strbuf.append(temp + "\r\n");
            }
            in.close();
            String result = strbuf.toString();
            return result;

        } catch (FileNotFoundException e1) {
            LOG.error(PlatformConstants.ERRINFO_FILENOTFOUNDEXCEPTION + remoteUrl, e1);
            return createOutXML(PlatformConstants.ERRINFO_FILENOTFOUNDEXCEPTION);
        } catch (java.net.SocketTimeoutException e2) {
            LOG.error(PlatformConstants.ERRINFO_TIMEOUTEXCEPTION, e2);
            return createOutXML(PlatformConstants.ERRINFO_TIMEOUTEXCEPTION);
        } catch (java.net.SocketException e3) {
            LOG.error(PlatformConstants.ERRINFO_SOCKETEXCEPTION, e3);
            return createOutXML(PlatformConstants.ERRINFO_SOCKETEXCEPTION);
        } catch (Exception e) {
            LOG.error(PlatformConstants.ERRINFO_OTHEREXCEPTION, e);
            return createOutXML(PlatformConstants.ERRINFO_OTHEREXCEPTION);

        } finally {
            if (hconn != null)
                hconn.disconnect();
            if (writer != null)
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    /**
     * <desc>
     * 使用淘宝免费接口获取ip地址归属地
     * </desc>
     *
     * @param ip ip地址
     * @return 查询ip归属地VO
     * @author wangzhi
     * @createDate 2018/12/19
     */
    public static IpGetAddressFromTaobaoVO getIpAddress(String ip) {
        try {
            String url = "http://ip.taobao.com/service/getIpInfo.php?ip=" + ip;
            String jsonStr = HttpProtocolUtil.doGet(url, null);
            if (StringUtils.isNotBlank(jsonStr)) {
                Map<String, Object> jsonToMap = JsonUtil.JsonToMap(jsonStr);
                if (jsonToMap != null && !jsonToMap.isEmpty()) {
                    IpGetAddressFromTaobaoVO ipGetAddressFromTaobaoVO = JsonUtil.toObject(jsonToMap.get("data").toString(), IpGetAddressFromTaobaoVO.class);
                    if (ipGetAddressFromTaobaoVO != null) {
                        return ipGetAddressFromTaobaoVO;
                    }
                }
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * <desc>
     *      请求微信小程序后台
     * </desc>
     *
     * @return
     * @author Juguang.S
     * @createDate 2018/12/07
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式（GET/POST）
            conn.setRequestMethod(requestMethod);

            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            jsonObject = JSONObject.parseObject(buffer.toString());
        } catch (ConnectException ce) {
            System.out.println("连接超时");
            LOG.info("【发送外部请求异常：】", ce);
        } catch (Exception e) {
            System.out.println("https请求异常");
            LOG.info("【发送外部请求异常：】", e);
        }
        return jsonObject;
    }
}
